﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Lyh.Train.Common.Http;
using Lyh.Train.Common.Mail;
using Lyh.Train.Common.Net;
using Lyh.Train.Recognizer.UUWise;
using System.Diagnostics;
using Lyh.Train.Data;
using Lyh.Train.Service;
using Lyh.Train.Common.Convertor;
using Lyh.Train.UI.Properties;

namespace Lyh.Train.UI
{
    public partial class MainForm : BaseForm
    {
        #region --Private Varies--

        private long runTimes = 0;
        private bool isUULogin = false;
        private bool isLogin = false;
        private string loginRandCode = string.Empty;
        private bool isCheckRandCodePass = false;
        private bool submit = false;
        private int codeId = 0;
        private readonly Color defaultColor = Color.White;
        private readonly Color errorColor = Color.Red;
        private readonly Color successColor = Color.Lime;
        private readonly Color warningColor = Color.Yellow;
        private List<QueryLeftNewDTOData> trainData = new List<QueryLeftNewDTOData>();
        private StringBuilder passengerTicketStr = new StringBuilder();
        private StringBuilder oldPassengerStr = new StringBuilder();
        private Token token;
        private string orderRandCode;
        private TicketService ticketService = new TicketService(Context.Cookies);
        private Condition condition; 

        #endregion

        #region --MainForm--

        public MainForm()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            SetSystem();

            SendMail();
        } 

        #endregion

        #region --Form Action--

        private void MaiForm_Load(object sender, EventArgs e)
        {
            if (!bwInit.IsBusy) bwInit.RunWorkerAsync();
        }

        private void btnUULogin_Click(object sender, EventArgs e)
        {
            if (!bwUULogin.IsBusy) bwUULogin.RunWorkerAsync();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            if (!CheckLoginInput()) return;
            if (!bwCheckRandCode.IsBusy) bwCheckRandCode.RunWorkerAsync();
        }

        private void txtRandCode_TextChanged(object sender, EventArgs e)
        {
            if (txtRandCode.Text.Trim().Length != 4) return;
            loginRandCode = txtRandCode.Text.Trim();
            btnLogin.PerformClick();
        }

        private void lnkAddTrain_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            using (var frm = new TrainSearchForm())
            {
                frm.OnAddingTrain += new TrainSearchForm.AddingTrainHandler(frm_OnAddingTrain);
                frm.ShowDialog();
            }
        }

        private void frm_OnAddingTrain(object sender, List<QueryLeftNewDTOData> data)
        {
            trainData = data;
            BindTrains();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            var msg = CheckStartInput();
            if (!string.IsNullOrWhiteSpace(msg))
            {
                ScrollMessage(msg,warningColor);
                return;
            }
            submit = false;
            ScrollMessage("已启动自动订票.");
            SetUIEnable(false);
            timer.Interval = (int)nudTick.Value;
            timer.Start();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            ScrollMessage("已停止自动订票.");
            timer.Stop();
            SetUIEnable(true);
        }

        private void miAbout_Click(object sender, EventArgs e)
        {
            About();
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            ConfirmExit();
        }

        private void miClearOut_Click(object sender, EventArgs e)
        {
            txtOut.Clear();
        }

        private void MaiForm_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.F3:
                    btnLogin.PerformClick();
                    break;
                case Keys.F4:
                    btnUULogin.PerformClick();
                    break;
                case Keys.F5:
                    btnStart.PerformClick();
                    break;
                case Keys.F6:
                    btnStop.PerformClick();
                    break;
            }
        }

        private void txtOut_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            Process.Start(e.LinkText);
        }

        private void lnkAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            for (var i = 0; i < clbTrain.Items.Count; i++)
            {
                clbTrain.SetItemChecked(i, true);
            }
        }

        private void lnkInvert_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            for (var i = 0; i < clbTrain.Items.Count; i++)
            {
                clbTrain.SetItemChecked(i, !clbTrain.GetItemChecked(i));
            }
        }

        private void txtOrderRandCodeString_TextChanged(object sender, EventArgs e)
        {
            if (txtOrderRandCodeString.Text.Trim().Length != 4) return;
            orderRandCode = txtOrderRandCodeString.Text.Trim();
            if (!bwConfirmOrder.IsBusy) bwConfirmOrder.RunWorkerAsync();
        }

        #endregion

        #region --Private Method--

        private void SetSystem()
        {
            Text = Context.SystemName;
            notifyIcon.BalloonTipTitle = Context.SystemName;

            var tip = new ToolTip();
            tip.SetToolTip(pbRandCodeImage, "单击刷新验证码");

            dtpFromDate.Value = DateTime.Now.AddDays(Context.BeforeDay);
            dtpToDate.Value = DateTime.Now.AddDays(Context.BeforeDay);

            var d1 = DateTime.Now.AddDays(Context.BeforeDay);
            var d2 = d1.AddDays(5);
            lblStatusText.Text = string.Format("今天可预订{0}的票--临客可预定{1}的票", d1.ToString("MM月dd日"), d2.ToString("MM月dd日"));
        }

        private void SendMail()
        {
            var body = TicketHelper.GetNoCompleteData();
            if (string.IsNullOrWhiteSpace(body)) return;
            var p = Context.Passengers[0];
            body = string.Format("{0}，恭喜您，您的12306帐号[{1}]订票成功！{2}", Context.RealName, Context.UserName, body);
            var to = p.email;
            var subject = string.Format("{0}--购票信息", Context.SystemName);
            MailHelper.Send(Context.MailAddress, to, subject, body);

            var player = new SoundPlayer(Resources.Message);
            player.PlayLooping();
            MessageBox.Show(body, Context.SystemName, MessageBoxButtons.OK, MessageBoxIcon.Information);
            player.Stop();
        }

        private void LoadStations()
        {
            Context.Stations = JsonHelper.FromJson<List<Station>>(Resources.Stations);
        }

        private void LoadSeats()
        {
            Context.Seats = JsonHelper.FromJson<List<Seat>>(Resources.Seats);
            clbSeat.DataSource = Context.Seats;
            clbSeat.ValueMember = "Code";
            clbSeat.DisplayMember = "Text";
        }

        private void BindPassengers()
        {
            TicketHelper.GetPassengers();
            clbPassenger.DataSource = Context.Passengers;
            clbPassenger.ValueMember = "code";
            clbPassenger.DisplayMember = "passenger_name";
            clbPassenger.Format += new ListControlConvertEventHandler(clbPassenger_Format);
        }

        private void clbPassenger_Format(object sender, ListControlConvertEventArgs e)
        {
            var p = e.ListItem as PassengerDTOs;
            if (p == null) return;
            e.Value = string.Format("{0}\t{1}\t{2}\t{3}", p.passenger_name, p.passenger_id_type_name, p.passenger_id_no, p.mobile_no);
        }

        private void BindTrains()
        {
            clbTrain.DataSource = trainData;
            clbTrain.ValueMember = "secretStr";
            clbTrain.DisplayMember = "secretStr";
            clbTrain.Format += new ListControlConvertEventHandler(clbTrain_Format);
        }

        private void clbTrain_Format(object sender, ListControlConvertEventArgs e)
        {
            var data = e.ListItem as QueryLeftNewDTOData;
            if (data == null) return;
            var t = data.queryLeftNewDTO;
            e.Value = string.Format("{0}\t{1}({3})\t→\t{2}({4})\t\t{5}", t.station_train_code, t.from_station_name, t.to_station_name, t.start_time, t.arrive_time, t.lishi);
        }

        private void ScrollMessage(string msg)
        {
            ScrollMessage(msg, defaultColor);
        }

        private void ScrollMessage(string msg, Color color)
        {
            Output(txtOut, msg, color);
        }

        private List<DateTime> GetOrderDateTimes()
        {
            var dates = new List<DateTime>();
            for (var t = dtpFromDate.Value.Date; t <= dtpToDate.Value.Date; t = t.AddDays(1))
            {
                dates.Add(t);
            }
            return dates;
        }

        private void CheckNetStatus()
        {
            var num = 0;
            var flag = InternetHelper.InternetGetConnectedState(out num, num);
            ScrollMessage("正在检测网络环境...");
            if (flag)
                ScrollMessage("检测网络环境完毕,网络畅通.");
            else
                ScrollMessage("网络未连通,请检查网络设置.", warningColor);
        }

        private void SetUIEnable(bool flag)
        {
            gbLogin12306.Enabled = flag;
            gbLoginUU.Enabled = flag;
            gbPassenger.Enabled = flag;
            gbSeat.Enabled = flag;
            gbSeting.Enabled = flag;
            gbTrain.Enabled = flag;
            btnStart.Enabled = flag;
            btnStop.Enabled = !flag;
            pbLoading.Enabled = !flag;
            pbLoading.Visible = !flag;
        }

        private bool CheckLoginInput()
        {
            if (string.IsNullOrWhiteSpace(txtUserName.Text))
            {
                ScrollMessage("请输入12306帐号登录名.", warningColor);
                txtUserName.Focus();
                return false;
            }
            if (string.IsNullOrWhiteSpace(txtPassword.Text))
            {
                ScrollMessage("请输入12306帐号密码.", warningColor);
                txtPassword.Focus();
                return false;
            }
            return true;
        }

        private string CheckStartInput()
        {
            var sb = new StringBuilder();
            condition = GetCondition();
            if (condition.Dates.Count < 1)
            {
                sb.Append("请选择乘车日期.");
            }
            if (condition.Passengers.Count < 1)
            {
                sb.Append("请选择乘车人.");
            }
            if (condition.Passengers.Count > 5)
            {
                sb.Append("最多只能选择5个乘车人.");
            }
            if (condition.Seats.Count < 1)
            {
                sb.Append("请选择席别.");
            }
            if (condition.Trains.Count < 1)
            {
                sb.Append("请选择车次.");
            }
            return sb.ToString();
        }

        private void ShowRand(object obj)
        {
            var img = obj as Image;
            if (img == null) return;
            pnlRandCode.Visible = true;
            pbOrderRandCodeImage.Image = img;
            Show();
            Activate();
            txtOrderRandCodeString.Focus();
        }

        #endregion

        #region --Condition--

        private List<PassengerDTOs> GetOrderPassengers()
        {
            return clbPassenger.CheckedItems.Cast<PassengerDTOs>().ToList();
        }

        private List<Seat> GetOrderSeatTypes()
        {
            return clbSeat.CheckedItems.Cast<Seat>().ToList();
        }

        private List<QueryLeftNewDTOData> GetOrderTrains()
        {
            return clbTrain.CheckedItems.Cast<QueryLeftNewDTOData>().ToList();
        }

        private Condition GetCondition()
        {
            var con = new Condition()
            {
                Dates = GetOrderDateTimes(),
                Passengers = GetOrderPassengers(),
                Seats = GetOrderSeatTypes(),
                Trains = GetOrderTrains()
            };
            return con;
        }

        #endregion

        #region --Order Logic--

        private bool AutoSubmit()
        {
            foreach (var date in condition.Dates)
            {
                foreach (var train in condition.Trains)
                {
                    runTimes++;
                    txtOrderRandCodeString.Text = string.Empty;
                    ScrollMessage(string.Format("开始第{0}次查询...", runTimes));
                    var tempTrains = TicketHelper.GetTrainDatas(date.ToString("yyyy-MM-dd"), train.queryLeftNewDTO.from_station_telecode, train.queryLeftNewDTO.to_station_telecode);
                    if (tempTrains == null || tempTrains.Count < 1)
                    {
                        ScrollMessage(string.Format("未查询出[{0}→{1}]的余票信息.", train.queryLeftNewDTO.from_station_name, train.queryLeftNewDTO.to_station_name), errorColor);
                        continue;
                    }
                    var orderTrain = tempTrains.SingleOrDefault(m => m.queryLeftNewDTO.station_train_code == train.queryLeftNewDTO.station_train_code);
                    if (orderTrain == null)
                    {
                        ScrollMessage(string.Format("未查询出{0}次列车余票信息.", train.queryLeftNewDTO.station_train_code), errorColor);
                        continue;
                    }
                    ScrollMessage(orderTrain.queryLeftNewDTO.ToString());
                    foreach (var seat in condition.Seats)
                    {
                        if (!TicketHelper.HasTicket(orderTrain, seat)) continue;
                        var qe = new QueryEntity
                        {
                            train_date = date.ToString("yyyy-MM-dd"),
                            SeatType = seat,
                            from_station_telecode_name = orderTrain.queryLeftNewDTO.from_station_name,
                            to_station_telecode_name = orderTrain.queryLeftNewDTO.to_station_name
                        };
                        OrderTicket(orderTrain, condition.Passengers, qe);
                        while (true)
                        {
                            if (!bwConfirmOrder.IsBusy) break;
                        }
                        if (!submit) continue;
                        timer.Stop();
                        return true;
                    }
                }
            }
            return false;
        } 

        private void OrderTicket(QueryLeftNewDTOData train, List<PassengerDTOs> passengers, QueryEntity qe)
        {
            ScrollMessage("开始订票...");

            var names = passengers.Aggregate(string.Empty, (current, passenger) => current + passenger.passenger_name + ",").TrimEnd(',');
            ScrollMessage(string.Format("开始为[{0}]预订[{1}][{2}]次[{3}]票...", names, qe.train_date, train.queryLeftNewDTO.station_train_code, qe.SeatType.Text));

            passengerTicketStr.Clear();
            oldPassengerStr.Clear();
            foreach (var passenger in passengers)
            {
                passengerTicketStr.AppendFormat("{0},0,1,{1},{2},{3},{4},N_", qe.SeatType.Value, passenger.passenger_name, passenger.passenger_id_type_code, passenger.passenger_id_no, passenger.mobile_no);
                oldPassengerStr.AppendFormat("{0},{1},{2},1_", passenger.passenger_name, passenger.passenger_id_type_code, passenger.passenger_id_no);
            }

            //第一步
            ScrollMessage("正在提交订单请求...");
            var autoSubmitOrderRequestResult = ticketService.AutoSubmitOrderRequest(train, qe, passengers);
            if (autoSubmitOrderRequestResult == null)
            {
                ScrollMessage("提交订单请求失败.", errorColor);
                submit = false;
                return;
            }
            if (!autoSubmitOrderRequestResult.status || autoSubmitOrderRequestResult.data == null || !autoSubmitOrderRequestResult.data.submitStatus)
            {
                var s = string.Empty;
                if (autoSubmitOrderRequestResult.messages != null && autoSubmitOrderRequestResult.messages.Count > 0)
                {
                    s = autoSubmitOrderRequestResult.messages.Aggregate(string.Empty, (current, message) => current + string.Format("{0},", message)).TrimEnd(',');
                    s = s.Replace("<a href=\"../queryOrder/initNoComplete\">[未完成订单]</a>", string.Format(" {0} ", Context.InitNoCompleteUrl)).Replace("，", ",").Replace("！", "").Replace("!", "");
                }
                ScrollMessage(string.Format("提交订单请求失败,{0}.", s), errorColor);
                submit = false;
                return;
            }
            var tokens = autoSubmitOrderRequestResult.data.result.Split('#');
            if (tokens.Length < 3)
            {
                ScrollMessage("提交订单请求失败.", errorColor);
                submit = false;
                return;
            }
            ScrollMessage("成功提交订单请求.");

            token = new Token
            {
                Q = tokens[0],
                LongToken = tokens[1],
                ShortToken = tokens[2]
            };

            //第二步
            ScrollMessage("正在查询排队详情...");
            var getQueueCountAsyncDataResult = ticketService.GetQueueCountAsync(train, qe, passengers, token);
            if (getQueueCountAsyncDataResult == null)
            {
                ScrollMessage("查询排队详情失败.", errorColor);
                submit = false;
                return;
            }
            if (!getQueueCountAsyncDataResult.status || getQueueCountAsyncDataResult.data == null)
            {
                var s = getQueueCountAsyncDataResult.messages.Aggregate(string.Empty, (current, message) => current + string.Format("{0},", message)).TrimEnd(',');
                ScrollMessage(string.Format("查询排队详情失败,{0}.", s), errorColor);
                submit = false;
                return;
            }
            ScrollMessage(string.Format("本次列车您选择的[{0}]尚有余票{1}张.", qe.SeatType.Text, getQueueCountAsyncDataResult.data.count));
            if (getQueueCountAsyncDataResult.data.op_2 == "true") ScrollMessage("目前排队人数已经超过余票张数,请您选择其他席别或车次.", errorColor);
            if (getQueueCountAsyncDataResult.data.countT != "0") ScrollMessage(string.Format("目前排队人数{0}人.", getQueueCountAsyncDataResult.data.countT));
            ScrollMessage("成功查询排队详情.");
            token.ticket = getQueueCountAsyncDataResult.data.ticket;

            //第三步
            ScrollMessage("正在获取验证码图片...");
            var randCodeImage = ticketService.GetOrderRandCodeImage();
            if (randCodeImage == null)
            {
                ScrollMessage("获取验证码图片失败.", errorColor);
                submit = false;
                return;
            }
            ScrollMessage("成功获取验证码图片.");
            ScrollMessage("正在自动识别验证码(可以手工填写)...");
            Invoke(new CommonHandler(ShowRand), randCodeImage.Clone());

            var res = new StringBuilder();
            var id = RandCodeHelper.GetRandCodeString(randCodeImage, Context.CodeType, ref res);
            if (id > 0)
            {
                orderRandCode = res.ToString();
                ScrollMessage(string.Format("成功识别验证码[{0}].", orderRandCode));
                txtOrderRandCodeString.Text = orderRandCode;
            }
            else
            {
                ScrollMessage("自动识别验证码失败,自动切换至人工录入模式,请在30秒内填入验证码.", errorColor);
                Invoke(new CommonHandler(ShowRand), randCodeImage.Clone());
                Thread.Sleep(30000);
                submit = false;
            }
        }

        private void ConfirmOrder()
        {
            //第四步
            ScrollMessage("正在确认订单...");
            var confirmSingleForQueueAsysData = ticketService.ConfirmSingleForQueueAsys(passengerTicketStr.ToString(), oldPassengerStr.ToString(), token, orderRandCode);
            if (confirmSingleForQueueAsysData == null)
            {
                ScrollMessage("确认订单失败.", errorColor);
                submit = false;
                return;
            }
            if (!confirmSingleForQueueAsysData.status || confirmSingleForQueueAsysData.data == null || !confirmSingleForQueueAsysData.data.submitStatus)
            {
                var s = confirmSingleForQueueAsysData.messages.Aggregate(string.Empty, (current, message) => current + string.Format("{0},", message)).TrimEnd(',');
                if (string.IsNullOrWhiteSpace(s)) s = "验证码错误";
                ScrollMessage(string.Format("确认订单失败,{0}.", s), errorColor);
                submit = false;
                return;
            }
            ScrollMessage("订单确认成功,正在检查订单状态...");

            while (true)
            {
                var result = TicketHelper.QueryOrderWaitTime(token.ShortToken);
                if (result == null || result.waitTime <= 0) break;
                var msg = (result.count > 0) ? string.Format("您前面还有{0}个订单要处理,大约需要等待{1}秒.", result.count, result.waitTime) : (string.Format("订单正在处理,大概需要等待{0}秒.", result.waitTime));
                ScrollMessage(msg);
                Thread.Sleep(500);
            }

            string not;
            var sw = new Stopwatch();
            sw.Start();
            while (true)
            {
                not = TicketHelper.GetNoCompleteData();
                if (!string.IsNullOrWhiteSpace(not) || (sw.ElapsedMilliseconds > 5000)) break;
            }
            sw.Stop();
            if (string.IsNullOrWhiteSpace(not))
            {
                ScrollMessage("出票失败,可能没有足够的票.", errorColor);
                submit = false;
                return;
            }

            submit = true;
            ScrollMessage(string.Format("恭喜您,订票成功,{0}", not), warningColor);
            ScrollMessage("订票成功,请登录 https://kyfw.12306.cn/otn/login/init 确认.", successColor);
            ScrollMessage("本次订票结束.");
        }

        #endregion

        #region --Timer--

        private void timer_Tick(object sender, EventArgs e)
        {
            if (!bwStartService.IsBusy) bwStartService.RunWorkerAsync();
        }

        private void timerClock_Tick(object sender, EventArgs e)
        {
            var h = DateTime.Now.Hour;
            if (h >= 23 || (h >= 0 && h < 7))
            {
                if (!btnStart.Enabled) return;
                btnStop.PerformClick();
            }
            else
            {
                if (!btnStart.Enabled) return;
                pbRandCodeImage_Click(sender, e);
                btnStart.PerformClick();
            }
        }

        #endregion

        #region --Background Worker--

        #region 0.初始化程序

        private void bwInit_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();
                var msg = "正在初始化程序,请稍候...";
                ScrollMessage(msg);
                CheckNetStatus();
                LoadStations();
                LoadSeats();
                sw.Stop();
                msg = string.Format("程序初始化完成,耗时{0}毫秒.", sw.ElapsedMilliseconds);
                ScrollMessage(msg);
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwInit_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!bwGetRandCodeImage.IsBusy) bwGetRandCodeImage.RunWorkerAsync();
        }

        #endregion

        #region 1.获取验证码图片

        private void bwGetRandCodeImage_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                txtRandCode.Text = string.Empty;
                pbRandCodeImage.Image = Resources.myloading;
                var sw = new Stopwatch();
                sw.Start();
                var msg = "正在获取验证码图片...";
                ScrollMessage(msg);
                pbRandCodeImage.Image = RandCodeHelper.GetRandCodeImage(Context.LoginRandCodeUrl);
                sw.Stop();
                msg = string.Format("成功获取验证码图片,耗时{0}毫秒.", sw.ElapsedMilliseconds);
                ScrollMessage(msg);
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwGetRandCodeImage_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            txtRandCode.Clear();
            if (isUULogin)
            {
                if (!bwRandCodeString.IsBusy) bwRandCodeString.RunWorkerAsync();
            }
            else
            {
                if (!bwUULogin.IsBusy) bwUULogin.RunWorkerAsync();
            }
        }

        #endregion

        #region 2.识别帐号登录

        private void bwUULogin_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();
                var msg = "正在登录到优优云服务...";
                ScrollMessage(msg);
                UUWrapper.uu_setSoftInfo(Context.SoftId, Context.SoftKey);
                var res = UUWrapper.uu_login(txtUUUserName.Text.Trim(), txtUUPassword.Text.Trim());
                var score = UUWrapper.uu_getScore(txtUUUserName.Text.Trim(), txtUUPassword.Text.Trim());
                sw.Stop();
                Color color;
                if (res > 0)
                {
                    isUULogin = true;
                    color = defaultColor;
                    msg = string.Format("优优云服务登录成功,{0},{1},耗时{2}毫秒.", res, score, sw.ElapsedMilliseconds);
                }
                else
                {
                    isUULogin = false;
                    color = errorColor;
                    msg = string.Format("优优云服务登录失败,{0},{1},耗时{2}毫秒.", UUErrorCode.GetErrorText(res.ToString()), score, sw.ElapsedMilliseconds);
                }
                ScrollMessage(msg, color);
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwUULogin_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (isUULogin && !bwRandCodeString.IsBusy) bwRandCodeString.RunWorkerAsync();
        }

        #endregion

        #region 3.获取验证码文字

        private void bwRandCodeString_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();
                var msg = "正在自动识别验证码(可以手工填写)...";
                ScrollMessage(msg);
                var res = new StringBuilder();
                codeId = RandCodeHelper.GetRandCodeString((Image) pbRandCodeImage.Image.Clone(), Context.CodeType, ref res);
                sw.Stop();
                Color color;
                if (codeId > 0)
                {
                    loginRandCode = res.ToString();
                    color = successColor;
                    var v = UUErrorCode.GetErrorText(res.ToString());
                    msg = string.Format("自动识别成功,{0},{1},耗时{2}毫秒.",codeId , loginRandCode, sw.ElapsedMilliseconds);
                }
                else
                {
                    loginRandCode = string.Empty;
                    color = errorColor;
                    msg = string.Format("自动识别失败,{0},{1},耗时{2}毫秒.", UUErrorCode.GetErrorText(res.ToString()), "?", sw.ElapsedMilliseconds);
                }
                ScrollMessage(msg, color);
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwRandCodeString_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            txtRandCode.Text = loginRandCode;
        }

        #endregion

        #region 4.检查验证码

        private void bwCheckRandCode_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(txtRandCode.Text))
                {

                    ScrollMessage("请输入验证码.");
                    txtRandCode.Focus();
                    return;
                }
                var sw = new Stopwatch();
                sw.Start();
                var msg = "正在检查验证码...";
                ScrollMessage(msg);
                isCheckRandCodePass = RandCodeHelper.CheckRandCode(loginRandCode, string.Empty);
                Color color;
                if (isCheckRandCodePass)
                {
                    color = defaultColor;
                }
                else
                {
                    color = errorColor;
                    UUWrapper.uu_reportError(codeId);
                }
                sw.Stop();
                msg = string.Format("验证结果:{0},耗时{1}毫秒.", isCheckRandCodePass ? "验证码正确" : "验证码错误", sw.ElapsedMilliseconds);
                ScrollMessage(msg, color);
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwCheckRandCode_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!isCheckRandCodePass) return;
            if (!bwLogin12306.IsBusy) bwLogin12306.RunWorkerAsync();
        }

        #endregion

        #region 5.重新加载验证码图片

        private void pbRandCodeImage_Click(object sender, EventArgs e)
        {
            if (!bwGetRandCodeImage.IsBusy) bwGetRandCodeImage.RunWorkerAsync();
        }

        #endregion

        #region 6.登录到12306

        private void bwLogin12306_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                if (!CheckLoginInput()) return;
                var sw = new Stopwatch();
                sw.Start();
                var msg = "正在登录到12306服务...";
                ScrollMessage(msg);
                var ret = string.Empty;
                isLogin = LoginHelper.Login(txtUserName.Text.Trim(), txtPassword.Text.Trim(), loginRandCode, ref ret);
                Context.UserName = txtUserName.Text.Trim();
                if (isLogin)
                {
                    Context.RealName = ticketService.GetUserName();
                    sw.Stop();
                    msg = string.Format("帐号[{0}]登录12306服务成功,耗时{1}毫秒.", Context.UserName, sw.ElapsedMilliseconds);
                    ScrollMessage(msg);
                    msg = "正在加载常用联系人...";
                    sw.Restart();
                    ScrollMessage(msg);
                    BindPassengers();
                    sw.Stop();
                    msg = string.Format("成功加载{0}个常用联系人,耗时{1}毫秒.", Context.Passengers.Count, sw.ElapsedMilliseconds);
                    ScrollMessage(msg);
                }
                else
                {
                    sw.Stop();
                    msg = string.Format("帐号[{0}]登录12306服务失败,{1},耗时{2}毫秒.", Context.UserName, ret, sw.ElapsedMilliseconds);
                    ScrollMessage(msg, errorColor);
                }
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwLogin12306_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var tip = string.Format("当前登录用户:[{0}]{1}{2}易达火车票正在后台运行...", Context.UserName, Context.RealName, Environment.NewLine);
            lblUser.Text = Context.RealName;
            notifyIcon.BalloonTipText = tip;
            notifyIcon.Text = tip;
        }

        #endregion

        #region 7.开启服务

        private void bwStartService_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                submit = AutoSubmit();
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwStartService_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            txtOrderRandCodeString.Text = string.Empty;
            pbOrderRandCodeImage.Image = null;
            pnlRandCode.Visible = false;
            if (!submit) return;
            btnStop.PerformClick();
            Show();
            Activate();
            BeginInvoke(new MethodInvoker(SendMail));
        } 

        #endregion

        #region 8.确认订单

        private void bwConfirmOrder_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                ConfirmOrder();
            }
            catch (Exception ex)
            {
                ScrollMessage(ex.Message, errorColor);
            }
        }

        private void bwConfirmOrder_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            txtOrderRandCodeString.Text = string.Empty;
            pbOrderRandCodeImage.Image = Resources.myloading;
        } 

        #endregion

        #endregion

    }
}
